unit uapijk;

{$mode Delphi}

interface

uses
  Classes, SysUtils, dbstructures;

const
  GO_DLL_NAME = 'qiusql.dll';
  // General declarations
  MYSQL_ERRMSG_SIZE = 512;
  SQLSTATE_LENGTH = 5;
  SCRAMBLE_LENGTH = 20;

type

  PQIUSQL_FIELD = ^QIUSQL_FIELD;

  QIUSQL_FIELD = record
    Name: pansichar;   // Name of column
    org_name: pansichar;   // Name of original column (added after 3.23.58)
    table: pansichar;   // Table of column if column was a field
    org_table: pansichar;   // Name of original table (added after 3.23.58
    db: pansichar;   // table schema (added after 3.23.58)
    catalog: pansichar;   // table catalog (added after 3.23.58)
    def: pansichar;   // Default value (set by mysql_list_fields)
    length: longint;     // Width of column
    max_length: longint;     // Max width of selected set
    // added after 3.23.58
    name_length: cardinal;
    org_name_length: cardinal;
    table_length: cardinal;
    org_table_length: cardinal;
    db_length: cardinal;
    catalog_length: cardinal;
    def_length: cardinal;
    //***********************
    flags: cardinal;    // Div flags
    decimals: cardinal;    // Number of decimals in field
    charsetnr: cardinal;    // char set number (added in 4.1)
    _type: cardinal;    // Type of field. Se mysql_com.h for types
  end;

  QIUNET = record
    //vio: Pointer;
    buff: pansichar;
    buff_end: pansichar;
    write_pos: pansichar;
    read_pos: pansichar;
    //fd: integer;
    remain_in_buf: longint;
    length: longint;
    buf_length: longint;
    where_b: longint;
    max_packet: cardinal;
    max_packet_size: cardinal;
    pkt_nr: cardinal;
    compress_pkt_nr: cardinal;
    write_timeout: cardinal;
    read_timeout: cardinal;
    retry_count: cardinal;
    fcntl: integer;
    //remain_in_buf: longint;
    //length: longint;
    //buf_length: longint;
    //where_b: longint;
    return_status: Pointer;
    reading_or_writing: char;
    save_char: char;
    //no_send_ok: byte;
    compress: byte;
    last_errno: cardinal;
    error: char;
    last_error: pansichar;// array[1..MYSQL_ERRMSG_SIZE] of char;
    sqlstate: pansichar;  //array[1..SQLSTATE_LENGTH + 1] of char;
    //query_cache_query: Pointer;
    //report_error: byte;
    //return_errno: byte;
  end;

  PQIUSQL = ^QIUSQL;

  QIUSQL = record
    _net: QIUNET;
    connector_fd: pansichar;
    connectID: uint64;
    rowID: uint64;
    host: pansichar;
    user: pansichar;
    passwd: pansichar;
    unix_socket: pansichar;
    server_version: pansichar;
    host_info: pansichar;
    info: pansichar;
    db: pansichar;
    //charset: pansichar;
    fields: PQIUSQL_FIELD;
    //field_alloc:     MEM_ROOT;
    affected_rows: uint64;
    insert_id: uint64;      //test: SmallInt;
    extra_info: uint64;
    thread_id: longint;
    packet_length: longint;
    port: cardinal;
    client_flag: longint;
    server_capabilities: longint;
    protocol_version: cardinal;
    field_count: cardinal;
    server_status: cardinal;
    server_language: cardinal;
    warning_count: cardinal;
    //options: cardinal;
    status: byte;
    free_me: byte;
    reconnect: byte;
    scramble: array[1..SCRAMBLE_LENGTH + 1] of char;
    //rpl_pivot: byte;
    //master: PQIUSQL;
    //next_slave: PQIUSQL;
    //last_used_slave: PQIUSQL;
    //last_used_con: PQIUSQL;
    //stmts: Pointer;
    //methods: Pointer;
    thd: Pointer;
    unbuffered_fetch_owner: pbyte;
  end;

  // Added in Oct 2023, to fix usage of mysql_fetch_lengths(). See issue #1863
  PQIUSQL_LENGTHS = ^TQIUSQL_LENGTHS;
  TQIUSQL_LENGTHS = array[0..MaxInt div SizeOf(longword) - 1] of longword;

  QIUSQL_ROW = array[0..$ffff] of pansichar;
  PQIUSQL_ROW = ^QIUSQL_ROW;

  PQIUSQL_ROWS = ^QIUSQL_ROWS;

  QIUSQL_ROWS = record
    Next: PQIUSQL_ROWS;
    Data: PQIUSQL_ROW;
  end;

  QIUSQL_DATA = record
    Data: PQIUSQL_ROWS;
    Rows: int64;
    Fields: cardinal;
    //Data:       PQIUSQL_ROWS;  //移动到上面,根据8.20的代码
    //Alloc:      MEM_ROOT;
  end;
  PQIUSQL_DATA = ^QIUSQL_DATA;

  QIUSQL_RES = record
    row_count: int64;
    //field_count, current_field:     Integer; //移动到下面 跟DLl C的一致
    fields: PQIUSQL_FIELD;
    Data: PQIUSQL_DATA;
    data_cursor: PQIUSQL_ROWS;
    lengths: PLongInt;       // column lengths of current row
    //field_alloc:     MEM_ROOT;
    row: PQIUSQL_ROW;     // If unbuffered read
    current_row: PQIUSQL_ROW;     // buffer to current row
    //lengths:         PLongInt;       // column lengths of current row 移动到上面了
    //handle:          PMYSQL;         // for unbuffered reads
    field_count, current_field: cardinal;
    EOF: byte;           // Used my mysql_fetch_row
    is_ps: byte;
    metadata: cardinal;
  end;
  PQIUSQL_RES = ^QIUSQL_RES;


  TMyDbinfo = packed record
    server: pansichar;
    user: pansichar;
    paswd: pansichar;
    db: pansichar;
    port: integer;
  end;

  pMyDbinfo = ^TMyDbinfo;

  TResultInfo = packed record
    strid: pansichar;
    err: pansichar;
  end;
  pResultInfo = ^TResultInfo;

  TResultArrayInfo = packed record
    cols: PPAnsiChar;
    err: pansichar;
    len: integer;
  end;


  TControlCenter = record
    Id: integer;
    Xid: integer;
    DType: integer;
    Tid: integer;
  end;


  // 主机
  TSqlHost = record
    Id: integer;
    Name: pansichar;               // 主机别名
    Host: pansichar;  // 数据库服务器名称
    Port: integer;                  // 主机端口
    Remark: pansichar; // 备注
    Databasetype: integer;
    User: pansichar;
    Password: pansichar;
    Database: pansichar;
    Charset: pansichar;
    Locate: pansichar;// 备份位置
    Version: pansichar;
    Sqlpath: pansichar;
    Local: integer;
    Wmode: integer;
    ResOne: pansichar;
    ResTwo: pansichar;
    ResThree: pansichar;
    ResFour: pansichar;
    IdOne: integer;
    IdTwo: integer;
    IdThree: integer;
    IdFour: integer;
  end;

  PSqlHost = ^TSqlHost;
  PPSqlHost = ^PSqlHost;

  TResultArraySQLInfo = packed record
    sqlhosts: PPSqlHost;
    err: pansichar;
    len: integer;
  end;

  //test: UInt64;

  { TMainLib }

  TQiuLib = class(TDbLib)
    qiusql_init: function(res: PQIUSQL): PQIUSQL; cdecl;
    GetSqlDbConn: procedure(Id: integer; var ret: PQIUSQL); cdecl;
    qiusql_real_query: function(res: PQIUSQL; sql: pansichar): cardinal; cdecl; //out rowsID: PUInt64
    qiusql_next_result: function(res: PQIUSQL): cardinal; cdecl;
    qiusql_store_result: function(res: PQIUSQL): PQIUSQL_RES;
    qiusql_num_rows: function(res: PQIUSQL_RES): uint64; cdecl;
    qiusql_free_result: procedure(res: PQIUSQL_RES); cdecl;
    qiusql_affected_rows: function(res: PQIUSQL): uint64; cdecl;

    RowNext: function(RowID: pansichar): TResultArrayInfo; cdecl;
    InitCliModule: procedure(); cdecl;      //sqlhost: TSqlHost
    DLStore: procedure(sqlhost: TSqlHost; var ret: TResultInfo); cdecl;
    DLAll: function(): TResultArraySQLInfo cdecl;
    FreeResultInfo: procedure(var ret: TResultInfo); cdecl;
  protected
    procedure AssignProcedures; override;
  end;


var
  qiuLib: TQiuLib;

implementation

{ TMainLib }

procedure TQiuLib.AssignProcedures;
begin
  AssignProc(@qiusql_init, 'qiusql_init');
  AssignProc(@GetSqlDbConn, 'GetSqlDbConn');
  AssignProc(@qiusql_real_query, 'qiusql_real_query');
  AssignProc(@qiusql_next_result, 'qiusql_next_result');
  AssignProc(@qiusql_store_result, 'qiusql_store_result');
  AssignProc(@qiusql_num_rows, 'qiusql_num_rows');
  AssignProc(@qiusql_free_result, 'qiusql_free_result');
  AssignProc(@qiusql_affected_rows, 'qiusql_affected_rows');


  AssignProc(@RowNext, 'RowNext');
  AssignProc(@InitCliModule, 'InitCliModule');
  AssignProc(@DLStore, 'DLStore');
  AssignProc(@DLAll, 'DLAll');
  AssignProc(@FreeResultInfo, 'FreeResultInfo');
end;

end.
